/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package cz.muni.fi.pa165.carpark.dao;

import cz.muni.fi.pa165.carpark.entities.ServiceCheck;
import cz.muni.fi.pa165.carpark.entities.Vehicle;
import java.util.List;
import javax.persistence.EntityExistsException;
import javax.persistence.EntityManager;
import javax.persistence.EntityNotFoundException;
import javax.persistence.NoResultException;
import javax.persistence.PersistenceContext;
import javax.persistence.TypedQuery;
import org.springframework.stereotype.Repository;

/*
 *@author xborza
 */
@Repository
public class ServiceCheckDAOImpl implements ServiceCheckDAO {

    @PersistenceContext
    protected EntityManager em;

    @Override
    public void createCheck(ServiceCheck serviceCheck){

        validate(serviceCheck);
        if (serviceCheck.getId() != null) {
            throw new IllegalArgumentException("serviceCheck has set ID");
        }
        try {
            em.persist(serviceCheck); // fixed by Martin            
        } catch (EntityExistsException ex) {
            throw new IllegalArgumentException("ServiceCheck in DB allready");
        }
    }

    // em.find throws IllegalArgumentException if id is null or is not valid
    @Override
    public ServiceCheck retrieveCheck(Long id){
        if (id == null) {
            throw new NullPointerException();
        }
        ServiceCheck result = em.find(ServiceCheck.class, id); // can be null            
        return result;
    }

    // em.merge throws IllegalArgumentException if id is null 
    @Override
    public void updateCheck(ServiceCheck serviceCheck){
        validate(serviceCheck);
        if (serviceCheck.getId() == null) {
            throw new IllegalArgumentException();
        }

        try {
            em.merge(serviceCheck);
        } catch (EntityNotFoundException e) {
            throw new IllegalArgumentException(e);
        }
    }

    @Override
    public void deleteCheck(ServiceCheck serviceCheck){
        if (serviceCheck == null) {
            throw new NullPointerException();
        }
        if (serviceCheck.getId() == null) {
            throw new IllegalArgumentException("serviceCheck id is null");
        }
        ServiceCheck sc = em.find(ServiceCheck.class, serviceCheck.getId()); // fixed by Martin, in order to get into managed stage 
        // remove from vehicle collection
        em.remove(sc);
    }

    @Override
    public List<ServiceCheck> findAllServiceChecks(){
        TypedQuery<ServiceCheck> query = em.createQuery("SELECT s FROM ServiceCheck s", ServiceCheck.class);
        List<ServiceCheck> result = query.getResultList();
        return result;
    }

    @Override
    public Vehicle findServiceCheckVehicle(ServiceCheck check){
        try {
            TypedQuery<Vehicle> query = em.createQuery("SELECT v FROM Vehicle v WHERE :check MEMBER OF  v.controlServiceCheck", Vehicle.class);
            query.setParameter("check", check);
            Vehicle result = query.getSingleResult();
            return result;
        } catch (NoResultException e) {
            // no vehicle exists for this service check
            return null;
        }
    }

    @Override
    public List<ServiceCheck> getServiceChecksByActive(boolean active){
        TypedQuery<ServiceCheck> query = em.createQuery("SELECT s FROM ServiceCheck s WHERE s.isActive =:active", ServiceCheck.class);
        query.setParameter("active", active);
        List<ServiceCheck> result = query.getResultList();
        return result;
    }

    @Override
    public List<ServiceCheck> getServiceChecksByDone(boolean done){
        TypedQuery<ServiceCheck> query = em.createQuery("SELECT s FROM ServiceCheck s WHERE s.checkDone =:done", ServiceCheck.class);
        query.setParameter("done", done);
        List<ServiceCheck> result = query.getResultList();
        return result;
    }

    public static void validate(ServiceCheck serviceCheck) {
        if (serviceCheck == null) {
            throw new NullPointerException("validation: serviceCheck is null");
        }
        if (serviceCheck.getLastCheck() == -1) {
            throw new IllegalArgumentException("Last check is not SET!");
        }

        if (serviceCheck.isCheckDone()) {
            if (serviceCheck.getCheckInterval() < 0 || serviceCheck.getCheckPurpose() == null
                    || serviceCheck.getCheckPurpose().length() == 0) {
                throw new IllegalArgumentException("done serviceCheck has illegal attributes");
            }
        }
    }

    public void setEntityManager(EntityManager em) {
        this.em = em;
    }
}
